package RRD;

# TODO:
# - use RRDs
# - validate fields

use strict;
use warnings;
use RRD::Fields ':all';
use Data::Dumper;

sub new
{
  my ($class, %args) = @_;

  my $self = {
    %args,
  };

  bless ($self, $class);
}

sub run
{
  my ($self) = @_;

  my $global = $self->{db}->get_global_status;
  my $master;
  my $slave;
  if ($self->{master_db})
  {
    $master = $self->{master_db}->get_master_status;
    $slave = $self->{db}->get_slave_status;
  }

  $self->update ($global, $master, $slave);
}

sub create
{
  my ($self, $interval) = @_;

  return if (-e $self->{filename});

  my $types = field_types;

  my @dss = ();
  my ($name, $type);
  foreach my $field (@{$self->{fields}})
  {
    if (ref ($types->{$field}) eq 'HASH')
    {
      # name was too long, we have hash of info with name and type
      $name = $types->{$field}{name};
      $type = $types->{$field}{type};
    }
    else
    {
      # name is fine the value is the type
      $name = $field;
      $type = $types->{$field};
    }
    push (@dss, sprintf ('DS:%s:%s:%d:0:U', $name, $type, $interval * 2));
  }

  my $cmd = sprintf ('rrdtool create %s --step %d %s %s', $self->{filename},
    $interval, join (' ', @dss),
    #    1 min 4 hours         5 min 28 hours        1 hour 96 hours       1 day 395 days
    'RRA:AVERAGE:0.5:1:240 RRA:AVERAGE:0.5:5:336 RRA:AVERAGE:0.5:60:96 RRA:AVERAGE:0.5:1440:395');
  print $cmd."\n";
  system ($cmd);
}

sub update
{
  my ($self, $stats, $master, $slave) = @_;

  my %repl_stats;

  if ($master and $slave)
  {
    my $master_pos = $master->{Position};
    my $slave_read_pos = $slave->{Read_Master_Log_Pos};
    my $slave_exec_pos = $slave->{Exec_Master_Log_Pos};

    $master->{File} =~ /(\d+)$/;
    my $master_log = $1;
    $slave->{Master_Log_File} =~ /(\d+)$/;
    my $slave_read_log = $1;
    $slave->{Relay_Master_Log_File} =~ /(\d+)$/;
    my $slave_exec_log = $1;

    %repl_stats = (
      Master_log => $master_log,
      Master_position => $master_pos,
      Slave_read_log => $slave_read_log,
      Slave_read_position => $slave_read_pos,
      Slave_exec_log => $slave_exec_log,
      Slave_exec_position => $slave_exec_pos,
      # warning this one is kind of funky/fuzzy and not that useful, use the 
      # behinds below instead
      Slave_seconds_behind => $slave->{Seconds_Behind_Master},
      # the next three will return undefined if the lot file numbers don't 
      # match, which is about as good as we can do since we don't know
      # what the real delay is when that happens
      Slave_read_behind => ($master_log != $slave_read_log) ? 
        'U' : $master_pos - $slave_read_pos,
      Slave_exec_behind_read => ($slave_read_log != $slave_exec_log) ? 
        'U' : $slave_read_pos - $slave_exec_pos,
      Slave_exec_behind_master => ($master_log != $slave_exec_log) ? 
        'U' : $master_pos - $slave_exec_pos,
      Slave_io_running => $slave->{Slave_IO_Running} eq 'Yes' ? 1 : 0,
      Slave_sql_running => $slave->{Slave_SQL_Running} eq 'Yes' ? 1 : 0,
    );
  }

  my @fields = map { 
    defined ($stats->{$_}) ? $stats->{$_} : ($repl_stats{$_} || 0)
  } @{$self->{fields}};

  my $cmd = sprintf ('rrdtool update %s N:%s', $self->{filename},
    join (':', @fields));
  print $cmd."\n";
  system ($cmd);
}

1;
